﻿using B.WMS.AutoCode;
using B.WMS.InWareHouseManagementDtos;
using B.WMS.StandardReturn;
using B.WMS.WMSDtos.Inventory.OutPut;
using B.WMS.WMSDtos.Warehousety;
using B.WMS.WMSEntities.GoodsEntities;
using B.WMS.WMSEntities.Warehousety;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;

namespace B.WMS.InWareHouseManagement
{
    public class WareHouseManagementAppService : ApplicationService, IWareHouseManagementAppService
    {
        private readonly IRepository<InWareHouseModel, Guid> _wareHouseRepository;
        private readonly IRepository<Warehouse, Guid> _lsjWareHouseRepository;
        private readonly IRepository<Location, Guid> _lsjLocationRepository;
        private readonly IRepository<Goods, Guid> _goodsRepository;
        private readonly IRepository<IOWareHouseRecordModel, Guid> _ioWareHouseRepository;
        public WareHouseManagementAppService(IRepository<InWareHouseModel, Guid> wareHouseRepository, IRepository<Warehouse, Guid> lsjWareHouseRepository, IRepository<Location, Guid> lsjLocationRepository, IRepository<Goods, Guid> goodsRepository, IRepository<IOWareHouseRecordModel, Guid> ioWareHouseRepository)
        {
            _wareHouseRepository = wareHouseRepository;
            _lsjWareHouseRepository = lsjWareHouseRepository;
            _lsjLocationRepository = lsjLocationRepository;
            _goodsRepository = goodsRepository;
            _ioWareHouseRepository = ioWareHouseRepository;
        }
        /// <summary>
        /// 添加入库信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [UnitOfWork]
        public async Task<ApiResult<int>> CreateAsync(CreateWareHouseInput input)
        {
            var result = new ApiResult<int>();
            var wareHouseDto = ObjectMapper.Map<CreateWareHouseInput, InWareHouseModel>(input);
            wareHouseDto.Appid = AutoCode.AutoCode.GetCode("RK").Result.ResultData;
            wareHouseDto.Status = 1;//待入库
            wareHouseDto.Inwarehousedate = DateTime.Now;
            wareHouseDto.CreationTime = DateTime.Now;

            var lsjWareHouseEntity = await _lsjLocationRepository.GetAsync(x => x.LocationNo == input.LocationNo);

            if (lsjWareHouseEntity.UseStatus == 1)
            {
                return new ApiResult<int>
                {
                    Code = ApiCode.ParamError,
                    ResultData = 0,
                    Message = "该仓库中的库位已有商品，请选择其他库位！"
                };
            }

            lsjWareHouseEntity.UseStatus = 1;
            lsjWareHouseEntity.ContityId = input.Relationordernum;

            var wareHouseEntity = await _lsjWareHouseRepository.GetAsync(x => x.WarehouseNo == input.WarehouseId);
            var goodsEntity = await _goodsRepository.GetAsync(x => x.Goodscoding == input.Relationordernum);

            IOWareHouseRecordDto dto = new IOWareHouseRecordDto();
            dto.Appid = AutoCode.AutoCode.GetCode("IO").Result.ResultData;
            dto.Recordtype = 1;
            dto.Status = 1;
            dto.Operationdate = DateTime.Now;
            dto.Warehousename = wareHouseEntity.Warename;
            dto.Relationordernum = input.Relationordernum;
            dto.GoodsId = goodsEntity.Goodscoding;
            dto.GoodsName = goodsEntity.Goodsname;
            dto.Operationuser = input.Operator;
            dto.Num = goodsEntity.Num;
            dto.Util = goodsEntity.GoodsUnitId;
            dto.Money = goodsEntity.Num * goodsEntity.Storageprice;
            dto.Audituser = wareHouseDto.Audituser;
            dto.Auditdate = wareHouseDto.Auditdate;

            var ioWareHouseRecordDto = ObjectMapper.Map<IOWareHouseRecordDto, IOWareHouseRecordModel>(dto);
            ioWareHouseRecordDto.WarehouseId = input.WarehouseId;
            ioWareHouseRecordDto.LocationId = input.LocationNo;
            ioWareHouseRecordDto.CreationTime = DateTime.Now;

            await _ioWareHouseRepository.InsertAsync(ioWareHouseRecordDto);
            await _lsjLocationRepository.UpdateAsync(lsjWareHouseEntity);
            await _wareHouseRepository.InsertAsync(wareHouseDto);
            return new ApiResult<int>()
            {
                Code = ApiCode.Success,
                ResultData = 3,
                Message = "添加成功"
            };
        }

        /// <summary>
        /// 获取入库列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ApiPaging<GetWareHouseOutput>> GetListAsync(GetInWareHousePageInput input)
        {
            var result = await _wareHouseRepository.GetQueryableAsync();
            if (input.Inwarehousetype != 0)
            {
                result = result.Where(x => x.Inwarehousetype == input.Inwarehousetype);
            }
            if (input.Inwarehousedate1 != null)
            {
                result = result.Where(x => x.Inwarehousedate >= input.Inwarehousedate1);
            }
            if (input.Inwarehousedate2 != null)
            {
                input.Inwarehousedate2 = input.Inwarehousedate2.Value.AddDays(1);
                result = result.Where(x => x.Inwarehousedate <= input.Inwarehousedate2);
            }
            if (input.Status != 0)
            {
                result = result.Where(x => x.Status == input.Status);
            }
            if (!string.IsNullOrEmpty(input.WarehouseId))
            {
                result = result.Where(x => x.WarehouseId == (input.WarehouseId));
            }

            if (!string.IsNullOrEmpty(input.LocationNoId))
            {
                result = result.Where(x => x.LocationNo == (input.LocationNoId));
            }

            var totalCount = result.Count();
            var totalPage = (int)Math.Ceiling(totalCount * 1.0 / input.PageSize);
            var listDto = ObjectMapper.Map<List<InWareHouseModel>, List<GetWareHouseOutput>>(result.Where(x => !x.Isdeleted).ToList());
            //将listDto中的Warehousename和Locationname 赋值
            foreach (var item in listDto)
            {
                item.Warehousename = _lsjWareHouseRepository.GetAsync(x => x.WarehouseNo == item.WarehouseId).Result.Warename;
                item.Locationname = _lsjLocationRepository.GetAsync(x => x.LocationNo == item.LocationNo).Result.LocationName;
            }
            var pageList = listDto.OrderByDescending(x => x.Appid).Skip((input.PageIndex - 1) / input.PageSize).Take(input.PageSize).ToList();
            return new ApiPaging<GetWareHouseOutput>()
            {
                TotalData = totalCount,
                TotalPage = totalPage,
                PageDatas = pageList,
                Code = ApiCode.Success,
                Message = "获取成功"
            };
        }

        /// <summary>
        /// 获取仓库下拉框
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ApiResult<List<SelectWareHouseDto>>> GetSelectWareHouse()
        {
            var wareList = await _lsjWareHouseRepository.GetListAsync();
            var dtoList = ObjectMapper.Map<List<Warehouse>, List<SelectWareHouseDto>>(wareList);
            return new ApiResult<List<SelectWareHouseDto>>
            {
                Code = ApiCode.Success,
                Message = "获取成功",
                ResultData = dtoList
            };
        }

        /// <summary>
        /// 获取仓库所包含的库位下拉框
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ApiResult<List<SelectLocationDto>>> GetSelectLocation(string warehouseId)
        {
            var locationList = await _lsjLocationRepository.GetListAsync(x => x.Warehouseid == warehouseId);
            var dtoList = ObjectMapper.Map<List<Location>, List<SelectLocationDto>>(locationList);
            return new ApiResult<List<SelectLocationDto>>
            {
                Code = ApiCode.Success,
                Message = "成功",
                ResultData = dtoList
            };
        }
        /// <summary>
        /// 审核入库
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        [UnitOfWork]
        public async Task<ApiResult<int>> AuditAsync(AuditWareHouseInput input)
        {
            var inWareHouseEntity = await _wareHouseRepository.GetAsync(x => x.Appid == input.InWareHouseAppId);
            var lsjWareHouseEntity = await _lsjWareHouseRepository.GetAsync(x => x.WarehouseNo == inWareHouseEntity.WarehouseId);
            var goodsEntity = await _goodsRepository.GetAsync(x => x.Goodscoding == inWareHouseEntity.Relationordernum);
            var locationEntity = await _lsjLocationRepository.GetAsync(x=>x.ContityId == goodsEntity.Goodscoding);

            IOWareHouseRecordDto dto = new IOWareHouseRecordDto();
            dto.Appid = AutoCode.AutoCode.GetCode("IO").Result.ResultData;
            dto.Operationdate = DateTime.Now;
            dto.Warehousename = lsjWareHouseEntity.Warename;
            dto.Relationordernum = inWareHouseEntity.Relationordernum;
            dto.GoodsId = goodsEntity.Goodscoding;
            dto.GoodsName = goodsEntity.Goodsname;
            dto.Operationuser = inWareHouseEntity.Operator;
            dto.Num = goodsEntity.Num;
            dto.Util = goodsEntity.GoodsUnitId;
            dto.Money = goodsEntity.Num * goodsEntity.Storageprice;
            dto.Audituser = input.AuditUser;
            dto.Auditdate = DateTime.Now;
            
            if (input.RadioInfo == 2)
            {
                inWareHouseEntity.Status = 3;

                dto.Recordtype = 1;
                dto.Status = 5;

                var ioWareHouseRecordEntity = ObjectMapper.Map<IOWareHouseRecordDto, IOWareHouseRecordModel>(dto);

                ioWareHouseRecordEntity.WarehouseId = locationEntity.Warehouseid;
                ioWareHouseRecordEntity.LocationId = locationEntity.LocationNo;

                await _ioWareHouseRepository.InsertAsync(ioWareHouseRecordEntity);
                await _wareHouseRepository.UpdateAsync(inWareHouseEntity);

                return new ApiResult<int>
                {
                    Code = ApiCode.Success,
                    ResultData = 2,
                    Message = "取消入库成功！"
                };
            }
            else
            {
                inWareHouseEntity.Status = 2;

                inWareHouseEntity.Audituser = input.AuditUser;
                inWareHouseEntity.Auditdate = DateTime.Now;

                goodsEntity.Goodsstatus = 2;

                if (lsjWareHouseEntity.WsortingMax < lsjWareHouseEntity.Wsorting + goodsEntity.Num)
                {
                    return new ApiResult<int>
                    {
                        Code = ApiCode.SysError,
                        ResultData = 0,
                        Message = "仓库已满，请另寻仓库！"
                    };
                }

                lsjWareHouseEntity.Wsorting += goodsEntity.Num;

                dto.Recordtype = 1;
                dto.Status = 2;

                var ioWareHouseRecordEntity = ObjectMapper.Map<IOWareHouseRecordDto, IOWareHouseRecordModel>(dto);

                ioWareHouseRecordEntity.WarehouseId = locationEntity.Warehouseid;
                ioWareHouseRecordEntity.LocationId = locationEntity.LocationNo;

                await _ioWareHouseRepository.InsertAsync(ioWareHouseRecordEntity);
                await _lsjWareHouseRepository.UpdateAsync(lsjWareHouseEntity);
                await _goodsRepository.UpdateAsync(goodsEntity);
                await _wareHouseRepository.UpdateAsync(inWareHouseEntity);

                return new ApiResult<int>
                {
                    Code = ApiCode.Success,
                    ResultData = 4,
                    Message = "入库成功"
                };
            }
            
        }
        /// <summary>
        /// 获取出入库记录列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ApiPaging<IOWareHouseRecordDto>> GetIOWareHouseRecordListAsync(GetIOWareHouseRecordPageInput input)
        {
            var ioWareHouseRecordList = await _ioWareHouseRepository.GetQueryableAsync();
            if (input.Recordtype != 0)
            {
                ioWareHouseRecordList = ioWareHouseRecordList.Where(x => x.Recordtype == input.Recordtype);
            }
            if (input.Status != 0)
            {
                ioWareHouseRecordList = ioWareHouseRecordList.Where(x => x.Status == input.Status);
            }
            if (!string.IsNullOrEmpty(input.WarehouseId))
            {
                ioWareHouseRecordList = ioWareHouseRecordList.Where(x => x.WarehouseId == input.WarehouseId);
            }
            if (!string.IsNullOrEmpty(input.LocationId))
            {
                ioWareHouseRecordList = ioWareHouseRecordList.Where(x => x.LocationId == input.LocationId);
            }
            if (!string.IsNullOrEmpty(input.GoodsId))
            {
                ioWareHouseRecordList = ioWareHouseRecordList.Where(x => x.GoodsId == input.GoodsId);
            }
            if (input.OperationdateStart != null)
            {
                ioWareHouseRecordList = ioWareHouseRecordList.Where(x => x.Operationdate >= input.OperationdateStart);
            }
            if (input.OperationdateEnd != null)
            {
                input.OperationdateEnd = input.OperationdateEnd.Value.AddDays(1);
                ioWareHouseRecordList = ioWareHouseRecordList.Where(x => x.Operationdate < input.OperationdateEnd);
            }
            var totalCount = ioWareHouseRecordList.Count();
            var totalPage = (int)Math.Ceiling(totalCount*1.0/input.PageSize);
            var data = ioWareHouseRecordList.OrderByDescending(x => x.Operationdate).Skip((input.PageIndex - 1) * input.PageSize).Take(input.PageSize).ToList();
            var dataList = ObjectMapper.Map<List<IOWareHouseRecordModel>, List<IOWareHouseRecordDto>>(data);
            foreach (var item in dataList)
            {
                item.Warehousename = _lsjWareHouseRepository.GetAsync(x => x.WarehouseNo == item.WarehouseId).Result.Warename;
                item.Locationname = _lsjLocationRepository.GetAsync(x => x.LocationNo == item.LocationId).Result.LocationName;
            }
            return new ApiPaging<IOWareHouseRecordDto>()
            {
                TotalData = totalCount,
                TotalPage = totalPage,
                PageDatas = dataList,
                Code = ApiCode.Success,
                Message = "获取成功"
            };
        }
        /// <summary>
        /// 获取商品下拉列表
        /// </summary>
        /// <returns></returns>
        public async Task<ApiResult<List<SelectGoodsDto>>> GetSelectGoods()
        {
            var wareList = await _goodsRepository.GetListAsync();
            var dtoList = ObjectMapper.Map<List<Goods>, List<SelectGoodsDto>>(wareList);
            return new ApiResult<List<SelectGoodsDto>>
            {
                Code = ApiCode.Success,
                Message = "获取成功",
                ResultData = dtoList
            };
        }
    }
}
